import json, time
from typing import List, Dict, Any, Optional
import vim 
from utils.log_util import setup_logger

logger = setup_logger()
class TaskStep:
    """表示任务中的单个步骤"""
    def __init__(self, expected_text: str, optimal_command: str):
        self.expected_text = expected_text
        self.optimal_command = optimal_command
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'TaskStep':
        """从字典创建 TaskStep 实例"""
        return cls(
            expected_text=data.get('expectedText', ''),
            optimal_command=data.get('optimalCommand', '')
        )
    
    def to_dict(self) -> Dict[str, Any]:
        """将 TaskStep 转换为字典"""
        return {
            'expectedText': self.expected_text,
            'optimalCommand': self.optimal_command
        }

class Task:
    """表示一个完整的训练任务"""
    def __init__(
        self, 
        task_id: int, 
        description: str, 
        initial_text: str, 
        steps: List[TaskStep],
        mode: str = 'normal',
        max_allowed_keys: int = 0,
        hint: str = ''
    ):
        self.id = task_id
        self.description = description
        self.initial_text = initial_text
        self.steps = steps
        self.mode = mode
        self.max_allowed_keys = max_allowed_keys
        self.hint = hint
        self.current_step_index = 0
        self.current_text = initial_text
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'Task':
        """从字典创建 Task 实例"""
        steps = [TaskStep.from_dict(step_data) for step_data in data.get('steps', [])]
        return cls(
            task_id=data.get('id', 0),
            description=data.get('description', ''),
            initial_text=data.get('initialText', ''),
            steps=steps,
            mode=data.get('mode', 'normal'),
            max_allowed_keys=data.get('maxAllowedKeys', 0),
            hint=data.get('hint', '')
        )
    
    def to_dict(self) -> Dict[str, Any]:
        """将 Task 转换为字典"""
        return {
            'id': self.id,
            'description': self.description,
            'initialText': self.initial_text,
            'steps': [step.to_dict() for step in self.steps],
            'mode': self.mode,
            'maxAllowedKeys': self.max_allowed_keys,
            'hint': self.hint
        }
    
    @property
    def current_step(self) -> Optional[TaskStep]:
        """获取当前步骤"""
        if 0 <= self.current_step_index < len(self.steps):
            return self.steps[self.current_step_index]
        return None
    
    def is_completed(self) -> bool:
        """检查任务是否已完成"""
        return self.current_step_index >= len(self.steps)
    
    def check_step(self, current_text: str) -> bool:
        """检查当前步骤是否完成"""
        if not self.current_step:
            return False
        
        return current_text == self.current_step.expected_text
    
    def advance_step(self) -> bool:
        """前进到下一步骤"""
        if self.current_step_index < len(self.steps) - 1:
            self.current_step_index += 1
            return True
        return False
    
    def reset(self) -> None:
        """重置任务到初始状态"""
        self.current_step_index = 0
        self.current_text = self.initial_text

class TaskManager:
    """管理多个任务"""
    def __init__(self):
        self.task_num = 0
        self.tasks: List[Task] = []
        self.current_task_index = -1
    
    def load_from_json(self, json_path: str) -> bool:
        """从 JSON 文件加载任务"""
        try:
            with open(json_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            self.tasks = [Task.from_dict(task_data) for task_data in data]
            self.task_num = len(self.tasks)
            self.current_task_index = 0
            return True
        except Exception as e:
            print(f"Error loading tasks from JSON: {e}")
            return False
    
    def save_to_json(self, json_path: str) -> bool:
        """将任务保存到 JSON 文件"""
        try:
            with open(json_path, 'w', encoding='utf-8') as f:
                json.dump([task.to_dict() for task in self.tasks], f, indent=2)
            return True
        except Exception as e:
            print(f"Error saving tasks to JSON: {e}")
            return False
    
    @property
    def current_task(self) -> Optional[Task]:
        """获取当前任务"""
        if 0 <= self.current_task_index < len(self.tasks):
            return self.tasks[self.current_task_index]
        return None
    
    def set_current_task(self, task_id: int) -> bool:
        """设置当前任务"""
        for i, task in enumerate(self.tasks):
            if task.id == task_id:
                self.current_task_index = i
                task.reset()
                return True
        return False
    
    def get_next_task(self) -> Optional[Task]:
        """获取下一个任务"""
        if self.current_task_index < len(self.tasks) - 1:
            self.current_task_index += 1
            task = self.tasks[self.current_task_index]
            task.reset()
            return task
        return None
    
    def get_previous_task(self) -> Optional[Task]:
        """获取上一个任务"""
        if self.current_task_index > 0:
            self.current_task_index -= 1
            task = self.tasks[self.current_task_index]
            task.reset()
            return task
        return None

class UserActivityTracker:
    def __init__(self):
        self.last_activity_time = time.time()
        self.active_timer = None
    
    def record_activity(self):
        """记录用户活动时间点"""
        self.last_activity_time = time.time()
        
    def is_idle(self, idle_threshold=0.5):
        """检测是否处于空闲状态（单位：秒）"""
        return (time.time() - self.last_activity_time) >= idle_threshold

class VimRenderer:
    def __init__(self):
        pass
    
    def init(self, edit_window: int, info_window: int):
        self.edit_window = edit_window
        self.info_window = info_window

    def render(self, task: Task):
        # 渲染编辑区
        self._render_edit_window(task)
        
        # 渲染信息区
        self._render_info_window(task)
    
    def _render_edit_window(self, task: Task):

        # 切换到编辑窗口
        vim.command(f"{self.edit_window}wincmd w")
        
        # 清空缓冲区
        vim.command("%delete")
        
        # 设置 initialText
        vim.current.buffer[:] = task.initial_text.split('\n')
        
        # 设置缓冲区为可修改
        vim.command("setlocal modifiable")
        
        # 根据任务模式设置 Vim 模式
        if task.mode.lower() == 'insert':
            vim.command("startinsert")
        elif task.mode.lower() == 'visual':
            vim.command("normal! gv")
        # 默认为普通模式，不需要特殊处理
    
    def _render_info_window(self, task: Task):

        # 切换到信息窗口
        vim.command(f"{self.info_window}wincmd w")
        
        # 设置缓冲区为可修改
        vim.command("setlocal modifiable")
        
        # 清空缓冲区
        vim.command("%delete")
        
        # 准备信息区内容
        info_lines = [
            '=== Vim Trainer ===',
            '',
            f'Task ID: {task.id}',
            f'Description: {task.description}',
            f'Mode: {task.mode}',
            f'Max Allowed Keys: {task.max_allowed_keys}',
            '',
            '--- Hint ---',
            task.hint,
            '',
            '--- Steps ---'
        ]
        
        # 添加步骤信息
        for i, step in enumerate(task.steps):
            current_marker = ">> " if i == task.current_step_index else "   "
            info_lines.append(f"{current_marker}Step {i+1}:")
            info_lines.append(f"    Expected: {step.expected_text}")
            info_lines.append(f"    Command: {step.optimal_command}")
        
        # 设置信息区内容
        vim.current.buffer[:] = info_lines
        
        # 设置缓冲区为不可修改
        vim.command("setlocal nomodifiable")
        
        # 返回到编辑窗口
        vim.command(f"{self.edit_window}wincmd w")

    def check(self):  # 定义一个名为check的方法，属于某个类的实例方法

        """
        检查函数，用于执行检查操作
        
        该函数会通过vim命令在vim界面输出"Checking..."提示信息
        """
        # vim.command("echo 'Checking...'")  # 使用vim命令输出检查提示信息
        self._debug_info("Checking...")
        logger.info("Checking...")
    def _debug_info(self, debug_msg):
        vim.command(f"{self.info_window}wincmd w")
        
        # 设置缓冲区为可修改
        vim.command("setlocal modifiable")
        # 信息区追加内容
        vim.current.buffer.append('[Debug] %s'% debug_msg)

class TranierController:
    def __init__(self):
        self.task_manager = TaskManager()
        self.renderer = VimRenderer()
        self.tracker = UserActivityTracker()

    def init_renderer(self, edit_window, info_window):
        self.renderer.init(edit_window,info_window)
    def load_task_json(self, path):
        self.task_manager.load_from_json(path)
        self.set_current_task(0)
        if self.task_manager.current_task:
            self.renderer.render(self.task_manager.current_task)

    def set_current_task(self, task_id):
        self.task_manager.set_current_task(task_id)

    def check(self):
        self.renderer.check()

manager = TranierController()
